#ifndef __PHYSICS_H__
#define __PHYSICS_H__

#include "btBulletDynamicsCommon.h"

#define MAX_SUBSTEPS 5

#define DEFAULT_FRICTION 0.3
#define DEFAULT_LINEAR_DAMPING 0.5
#define DEFAULT_ANGULAR_DAMPING 0.5

#define CAR_MASS 1000.0
#define CAR_SUSPENSION_REST_LENGTH 1.0
#define CAR_SUSPENSION_STIFFNESS 100.0
#define CAR_SUSPENSION_DAMPING 10.0
#define CAR_SUSPENSION_COMPRESSION 10.0
#define CAR_ROLL_INFLUENCE 1.0
#define CAR_WHEEL_FRICTION 1000.0

#define CAR_MAX_STEERING_ANGLE 1.0
#define CAR_STEERING_ANGLE_PER_FRAME 0.02
#define CAR_ENGINE_FORCE 5000.0
#define CAR_BREAKING_FORCE 1000.0

class Physics
{
private :
	btScalar airplaneMass;
public:
	Physics(btVector3 &gravity = btVector3(0.0, -9.81, 0.0));
	~Physics();

	void stepSimulation(float deltaTime);
	void updateVehicle(float deltaTime);
	
	btRigidBody* addBox(btVector3 &halfExtents, btScalar mass, btVector3 &position, btQuaternion &orientation);
	btRigidBody* addSphere(btScalar radius, btScalar mass, btVector3 &position, btQuaternion &orientation);

	void setupVehicle(btVector3 &halfExtents, btScalar mass, btVector3 &position, btQuaternion &orientation);
	void addWheel(btScalar wheelWidth, btScalar wheelRadius, btVector3 &offset, bool isFrontWheel);

	enum Wheel_ID
	{
		W_FrontLeft,
		W_FrontRight,
		W_RearLeft,
		W_RearRight
	};
	
	void moveVehicle(float dx, float dy, float dz);
	void applyForceToVehicle(float dx, float dy, float dz);
	void applyTorqueToVehicle(float dx, float dy, float dz);
	void setPoseOfVehicle(float azi, float pitch, float roll);

	void goVehicleFoward();
	void goVehicleBackward();
	void turnVehicleLeft();
	void turnVehicleRight();
	void idleVehicle();
	void setGravity(float g);

	btAlignedObjectArray<btRigidBody*> mStaticBodyList;
	btAlignedObjectArray<btRigidBody*> mDynamicBodyList;

	btDynamicsWorld *mDynamicsWorld;

	btRigidBody* mVehicleBody;
	btRaycastVehicle* mRaycastVehicle;

protected:
	btDefaultCollisionConfiguration *mCollisionConfiguration;
	btCollisionDispatcher *mDispatcher;
	btDbvtBroadphase *mBroadphase;
	btSequentialImpulseConstraintSolver *mSolver;

	btVehicleRaycaster* mVehicleRaycaster;
	btRaycastVehicle::btVehicleTuning mVehicleTuning;
};

#endif